package com.qinggeng.project.api.controller;

import com.qinggeng.common.constant.Constants;
import com.qinggeng.common.enums.OrdersStatusEnum;
import com.qinggeng.common.enums.PayTypeEnum;
import com.qinggeng.common.enums.ShowTypeEnum;
import com.qinggeng.common.exception.CustomException;
import com.qinggeng.common.utils.StringUtils;
import com.qinggeng.framework.redis.RedisLock;
import com.qinggeng.framework.web.controller.BaseController;
import com.qinggeng.framework.web.domain.AjaxResult;
import com.qinggeng.project.api.security.annotation.LoginRequired;
import com.qinggeng.project.api.security.utils.ApiUtils;
import com.qinggeng.project.system.domain.Orders;
import com.qinggeng.project.system.domain.UserBindGsd;
import com.qinggeng.project.system.service.IOrdersService;
import com.qinggeng.project.system.service.UserBindGsdService;
import com.qinggeng.project.tool.pay.domain.vo.TradeVo;
import com.qinggeng.project.tool.pay.service.AliPayService;
import com.qinggeng.project.tool.pay.service.FreePayService;
import com.qinggeng.project.tool.pay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;

@Slf4j
@Api(tags = "支付模块")
@RestController
@RequestMapping("${apiPath}/pay")
@CrossOrigin("*")
public class ApiPayController extends BaseController {

    @Autowired
    private IOrdersService ordersService;

    @Autowired
    private AliPayService aliPayService;

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private FreePayService freePayService;

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserBindGsdService userBindGsdService;

    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    @ApiOperation("调用支付宝App支付")
    @GetMapping("/alipayAppPay")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = false),
            @ApiImplicitParam(name="ordersNo",value="订单编号",dataType="String", paramType = "query", required = true),
    })
    public AjaxResult alipayAppPay(String ordersNo){

        return appPay(ordersNo,PayTypeEnum.ALIPAY.getValue());
    }

    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    @ApiOperation("调用支付宝App周期支付")
    @GetMapping("/alipayAppCyclePaySign")
    public AjaxResult alipayAppCyclePaySign(Long id) {
        if(null == id){
            throw  new CustomException("id is  null");
        }
        String submitFormData="";
        try{
            submitFormData=aliPayService.sign(id);
        }catch (Exception e){
            e.printStackTrace();
            throw  new CustomException("签约失败");
        }
        return AjaxResult.success(submitFormData);
    }

    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    @ApiOperation("调用微信App支付")
    @GetMapping("/wxpayAppPay")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = false),
            @ApiImplicitParam(name="ordersNo",value="订单编号",dataType="String", paramType = "query", required = true),
    })
    public AjaxResult wxpayAppPay(String ordersNo){
        return appPay(ordersNo,PayTypeEnum.WXPAY.getValue());
    }

    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    @ApiOperation("小程序App支付")
    @GetMapping("/minipayAppPay")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = false),
            @ApiImplicitParam(name="ordersNo",value="订单编号",dataType="String", paramType = "query", required = true),
    })
    public AjaxResult minipayAppPay(String ordersNo){
        return appPay(ordersNo,PayTypeEnum.MINIPAY.getValue());
    }


    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    @ApiOperation("小程序App代付支付")
    @GetMapping("/miniPaymentOnBehalfOf")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = false),
            @ApiImplicitParam(name="ordersNo",value="订单编号",dataType="String", paramType = "query", required = true),
    })
    public AjaxResult paymentOnBehalfOf(String ordersNo){
        log.info("进入代付流程 {}",ordersNo);

        UserBindGsd userBindGsd = userBindGsdService.selectUserBindGsdByUserIdAndPlatform(ApiUtils.getUserId(), "wx_mini");
        if (userBindGsd == null){
            throw new CustomException("appPay().userBindGsd is null");
        }
        return appPay(ordersNo,PayTypeEnum.PAYMENT_ON_BEHALF_OF.getValue(),userBindGsd.getUniqueId());
    }

    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    @ApiOperation("免费支付")
    @GetMapping("/freePay")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = false),
            @ApiImplicitParam(name="ordersNo",value="订单编号",dataType="String", paramType = "query", required = true),
    })
    public AjaxResult freePay(String ordersNo){
        return appPay(ordersNo,PayTypeEnum.FREEPAY.getValue());
    }

    private AjaxResult appPay(String ordersNo,Integer payType){
        RedisLock redisLock = new RedisLock(redisTemplate,"payOrders:"+ ordersNo,3*1000,3*1000);
        if (!redisLock.lockNoRetry()){
            return AjaxResult.error("服务繁忙，请休息一会", ShowTypeEnum.用户.getValue());
        }
        try {
            Orders orders = ordersService.selectOrdersByOrdersNo(ordersNo);
            if (orders == null){
                return AjaxResult.error("订单不存在");
            }
            //解决订单超时仍然能支付的问题
            if(!orders.getStatus().equals(OrdersStatusEnum.进行中.getValue())){
                return AjaxResult.error("订单已关闭",ShowTypeEnum.用户.getValue());
            }
            TradeVo trade = new TradeVo();
            trade.setOutTradeNo(ordersNo);
            if (payType.equals(PayTypeEnum.MINIPAY.getValue())){
                UserBindGsd userBindGsd = userBindGsdService.selectUserBindGsdByUserIdAndPlatform(ApiUtils.getUserId(), "wx_mini");
                if (userBindGsd == null){
                    throw new CustomException("appPay().userBindGsd is null");
                }
                trade.setOpenid(userBindGsd.getUniqueId());
            }
            trade.setSubject("支付订单号："+trade.getOutTradeNo());
            trade.setBody("支付订单号："+trade.getOutTradeNo());
            if (Constants.DEBUG){
               trade.setTotalAmount(new BigDecimal(0.01+""));
            }else {
              trade.setTotalAmount(orders.getPayPrice());
           }
           /* trade.setTotalAmount(orders.getPayPrice());*/
            Object result=null;
            //支付宝支付
            if(payType== PayTypeEnum.ALIPAY.getValue()){
                result=aliPayService.toPayAsApp(trade);
            }
            //支付宝周期支付
            if(payType== PayTypeEnum.ALIPAY_CYCLE.getValue()){
                result=aliPayService.toPayAsApp(trade);
            }

            //微信支付
            if(payType==PayTypeEnum.WXPAY.getValue()){
                result=wxPayService.toPayAsApp(trade);
            }

            //小程序支付
            if(payType==PayTypeEnum.MINIPAY.getValue()){
                result=wxPayService.toPayAsMiniapp(trade);
            }

            //免费支付
            if(payType==PayTypeEnum.FREEPAY.getValue()){
                result=freePayService.toPayForFree(trade);
            }

            return AjaxResult.success(result);
        }catch (Exception e){
            log.error("调用支付异常",e);
            return AjaxResult.error("调用支付异常："+e.getMessage());
        }finally {
            redisLock.unlock();
        }
    }
    private AjaxResult appPay(String ordersNo,Integer payType,String openId){
        RedisLock redisLock = new RedisLock(redisTemplate,"payOrders:"+ ordersNo,3*1000,3*1000);
        if (!redisLock.lockNoRetry()){
            return AjaxResult.error("服务繁忙，请休息一会", ShowTypeEnum.用户.getValue());
        }
        try {
            Orders orders = ordersService.selectOrdersByOrdersNo(ordersNo);
            if (orders == null){
                return AjaxResult.error("订单不存在");
            }
            //解决订单超时仍然能支付的问题
            if(!orders.getStatus().equals(OrdersStatusEnum.进行中.getValue())){
                return AjaxResult.error("订单已关闭",ShowTypeEnum.用户.getValue());
            }
            TradeVo trade = new TradeVo();
            trade.setOutTradeNo(ordersNo);
            trade.setOpenid(openId);
            trade.setSubject("支付订单号："+trade.getOutTradeNo());
            trade.setBody("支付订单号："+trade.getOutTradeNo());
            if (Constants.DEBUG){
                trade.setTotalAmount(new BigDecimal(0.01+""));
            }else {
                trade.setTotalAmount(orders.getPayPrice());
            }
            /* trade.setTotalAmount(orders.getPayPrice());*/
            Object result=null;
            //小程序支付
            if(payType==PayTypeEnum.PAYMENT_ON_BEHALF_OF.getValue()){
                result=wxPayService.paymentOnBehalfOf(trade);
            }
            return AjaxResult.success(result);
        }catch (Exception e){
            log.error("调用支付异常",e);
            return AjaxResult.error("调用支付异常："+e.getMessage());
        }finally {
            redisLock.unlock();
        }
    }

    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    @ApiOperation("验证是否支付成功")
    @GetMapping("/isPaySuccess")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true),
            @ApiImplicitParam(name="ordersNo",value="订单编号",dataType="String", paramType = "query", required = true),
    })
    public AjaxResult isPaySuccess(String ordersNo){
        Integer payStatusSuccess=ordersService.selectPayStatusSuccess(ordersNo);//查询订单支付成功状态，1=成功
        return toAjax(payStatusSuccess);
    }

}
